#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;

//函数模板
template <class T>
T add(T t1, T t2){
    cout << "模板一" << endl;
    return t1 + t2;
}

template <class T1, class T2>
T1 add(T1 t1, T2 t2)
{
    cout << "模板二" << endl;
    return t1 + t2;
}

//根据指定的类型实例化出这样的模板函数
/* int add(int t1, int t2) */
/* { */
/*     return t1 + t2; */
/* } */

void test0(){
    short s1 = 1;
	int i2 = 4;
    //如果只有模板一
    //传入两个不同类型的参数，进行隐式实例化会报错
	/* cout << "add(s1,s2): " << add(s1,i2) << endl;*/
	cout << "add(s1,s2): " << add<int>(s1,i2) << endl;//ok
    cout << endl;

    int i1 = 4;
    double d2 = 5.3;
    //有了模板二，此时可以通过隐式实例化调用模板二
    cout << "add(i1,d2): " << add(d2,i1) << endl;
    cout << endl;

    //指定T1为double
    cout << "add(i1,d2): " << add<int>(i1,d2) << endl;
}

void test1(){
    int x = 4;
    double y = 7.6;
    //只能是模板二，模板二才支持指定两个模板参数
    cout << add<double,int>(x,y) << endl;

    //////调用模板二
    //指定T1为int，没有指定T2
    //传入的第一个参数本身就是int，不需要类型转换
    //传入的第二个参数推导出double
    //返回类型与第一个参数一致
    //使用模板二，对参数不需要进行任何的类型转换；
    //如果使用模板一，需要对y进行类型转换
    cout << add<int>(x,y) << endl;

    //指定第一个模板参数为double
    //无论是模板一还是模板二都需要对x进行类型转换
    //调用到模板一
    cout << add<double>(x,y) << endl;

}

int main(void){
    test1();
    return 0;
}
